/**
 * Copyright 2009-2010 - YangJiandong(chunquedong)
 * 
 * This file is part of ChunMap project
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE(Version >=3)
 * 你可以自由复制、传播本项目的下载包文件，但必须保持其完整性。
 * 我们不用对使用中的风险及由此造成的损失承担任何责任。
 * 详细情况请见《ChunMap许可协议》。

 * 想了解更多有关ChunMap的信息，请访问http://code.google.com/p/chunmap/
 */
package chunmap.raster.grid.operate;

import java.awt.Image;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.util.Calendar;

import javax.imageio.ImageIO;

import chunmap.data.feature.Raster;
import chunmap.model.elem.Envelope;
import chunmap.raster.grid.Grid;
import chunmap.raster.grid.GridLayer;
import chunmap.raster.grid.TileImpl;
import chunmap.view.Map;

/**
 * 切割地图为网格图片的工具
 * 
 * @author chunquedong
 * 
 */
public class ImageCut {
	private Map map;
	private String rootPath;
	private String formatName = "jpeg";

	
	public ImageCut(Map map, String rootPath) throws IOException {
		this.map = map;
		this.rootPath = rootPath;

		// 检查目录有效性chek directory
		File file = new File(rootPath);
		if (file.exists()) {
			if (!file.isDirectory() || !file.canWrite())
				throw new IOException(rootPath + " is not valid directory.");
		} else {
			file.mkdirs();
		}
	}

	public String getFormatName() {
		return formatName;
	}

	public void setFormatName(String formatName) {
		this.formatName = formatName;
	}

	// ---------------------------------------------------------------------

	public Grid cut(double scale, String parameters) throws IOException {
		// set scale
		map.fullView();

		map.getView().zoom(scale,0,0);

		// make directory
		double biLiChi = map.getView().getScale();
		String directoryName = parameters + "_" + biLiChi;
		String path = createDirectory(directoryName).getPath();

		// create grid
		Grid grid = new Grid();
		grid.setParameters(parameters);
		grid.setScale(biLiChi);
		grid.setSubEnvelop(map.getView().getViewEnvelop());

		createAllTile(grid, path);

		return grid;
	}

	private void createAllTile(Grid grid, String path) throws IOException {

		Envelope oenvelop = map.getLayerCollection().getEnvelop();

		double w = grid.getSubEnvelop().getWidth();
		double h = grid.getSubEnvelop().getHeight();
		double zw = oenvelop.getWidth();
		double zh = oenvelop.getHeight();
		// double vw = map.getView().getEnvelop().getWidth();
		// double vh = map.getView().getEnvelop().getHeight();
		double ox = oenvelop.getMinX();
		double oy = oenvelop.getMinY();

		double dn = zw / w + 0.4999;
		double dm = zh / h + 0.4999;
		int n = (int) Math.round(dn);
		int m = (int) Math.round(dm);

		double dx, dy;

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {

				// compute envelop
				dx = i * w + ox;
				dy = j * h + oy;

				// pixels expand
				// double dd = buffer / map.getView().getScale();

				Envelope envelop = new Envelope(dx, dy, dx + w, dy + h);
				map.getView().setViewEnvelop(envelop);
				// map.getView().pan(0, dy);

				createImage(grid, path, i, j);
			}
		}
	}

	private Raster createImage(Grid grid, String path, int x, int y)
			throws IOException {
		// save image
		map.render();
		Image image = (Image)map.getPainter().getData();

		String name = x + "_" + y + "." + formatName;
		File file = createFile(path, name);

		ImageIO.write((RenderedImage) image, formatName, file);

		// create tile
		TileImpl tile = new TileImpl();

		// Image imageCopy = copyImage(image);
		// tile.setData(imageCopy);

		tile.setEnvelop(map.getView().getViewEnvelop());
		tile.setX(x);
		tile.setY(y);
		tile.setParent(grid);
		grid.getTiles().add(tile);

		return tile;
	}

	// private Image copyImage(Image image) {
	// Image imageCopy = new BufferedImage((int)map.getView().getWidth(),
	// (int)map.getView().getHeight(), BufferedImage.TYPE_INT_RGB);
	// imageCopy.getGraphics().drawImage(image,0,0,null);
	// return imageCopy;
	// }

	private File createFile(String path, String name) throws IOException {
		File file = new File(path + File.separator + name);
		if (!file.exists()) {
			file.createNewFile();
		}
		return file;
	}

	private File createDirectory(String directoryName) {
		File file = new File(rootPath + File.separator + directoryName);
		file.mkdir();
		return file;
	}

	public GridLayer autoCut(double step, int num) throws IOException {
		double scale = 1;
		GridLayer layer = new GridLayer();
		layer.setEnvelop(map.getLayerCollection().getEnvelop());
		layer.setName(rootPath);

		// 时间戳
		Calendar rightNow = Calendar.getInstance();
		String pars = rightNow.getTimeInMillis() + "";

		Grid[] grids = new Grid[num];
		for (int i = 0; i < num; i++) {

			Grid grid = cut(scale, pars);
			grids[i] = grid;

			scale *= step;
		}
		layer.setGrids(grids);
		return layer;
	}
}
